package com.yjd.pub.fundservice.service;

import java.util.*;

import javax.annotation.Resource;

import com.alibaba.fastjson.JSON;
import com.yjd.comm.bank.model.BankModel;
import com.yjd.comm.base.enums.DbWREnums;
import com.yjd.comm.enums.*;
import com.yjd.comm.funds.dto.FundChannelConfigDto;
import com.yjd.comm.funds.service.IFundsService;
import com.yjd.comm.fundservice.dto.QKLoanApplyModel;
import com.yjd.comm.fundservice.dto.QKLoanApplyResponse;
import com.yjd.comm.fundservice.dto.QKRepaymentPlanModel;
import com.yjd.comm.fundservice.dto.RepaymentPlanItem;
import com.yjd.comm.fundservice.enums.BusTypeEnum;
import com.yjd.comm.fundservice.enums.FundChannelEnum;
import com.yjd.comm.fundservice.enums.LoanApplyStatusEnum;
import com.yjd.comm.fundservice.util.QianKangServer;
import com.yjd.comm.merchant.service.IMerchantFundsService;
import com.yjd.comm.msg.MnsMsgInfo;
import com.yjd.comm.order.model.OrderModel;
import com.yjd.comm.order.model.OrderRefuseContentModel;
import com.yjd.comm.order.model.OrderStatusModel;
import com.yjd.comm.order.service.IOrderRefuseContentService;
import com.yjd.comm.order.service.IOrderStatusService;
import com.yjd.comm.org.model.OrganizationModel;
import com.yjd.comm.org.service.IOrganizationService;
import com.yjd.comm.repayment.model.RepaymentDataModel;
import com.yjd.comm.system.util.SysParamUtil;
import com.yjd.comm.user.model.UserDataModel;
import com.yjd.comm.util.*;
import com.yjd.comm.vo.Constant;
import com.yjd.msg.comm.annotation.MnsDispose;
import com.yjd.pub.bank.dao.IBankDao;
import com.yjd.pub.order.dao.IOrderDao;
import com.yjd.pub.repayment.dao.IRepaymentDataDao;
import com.yjd.pub.user.dao.IUserDataDao;
import org.springframework.stereotype.Service;

import com.yjd.comm.base.dao.IBaseDao;
import com.yjd.comm.base.service.impl.BaseServiceImpl;
import com.yjd.comm.fundservice.model.FundLoanApplyModel;
import com.yjd.comm.fundservice.service.IFundLoanApplyService;
import com.yjd.pub.fundservice.dao.IFundLoanApplyDao;
import org.springframework.util.Assert;

/**
 * <b>description</b>：贷款申请业务实现<br>
 * <b>time</b>：2018-01-29 10:12:39 <br>
 * <b>author</b>：  yangchangyan@yijiedai.com
 */
@Service("fundLoanApplyService")
public class FundLoanApplyServiceImpl extends BaseServiceImpl implements IFundLoanApplyService {

	/**
	 * 插入
	 * 
	 * @param model
	 * @return
	 * @throws Exception
	 */
	public FundLoanApplyModel insert(FundLoanApplyModel model) throws Exception {
		return this.fundLoanApplyDao.insertModel(model, true);
	}

	/**
	 * 更新
	 * 
	 * @param model
	 * @return
	 * @throws Exception
	 */
	public int update(FundLoanApplyModel model) throws Exception {
		return this.fundLoanApplyDao.updateModel(model, true);
	}

	/**
	 * 根据id删除
	 * 
	 * @param id
	 * @return
	 * @throws Exception
	 */
	public int delete(long id) throws Exception {
		Map<Object, Object> paramMap = new HashMap<Object, Object>();
		paramMap.put("id", id);
		return this.fundLoanApplyDao.deleteModel(paramMap, true);
	}

	@MnsDispose
	@Override
	public void loanApplyMsgDispose(MnsMsgInfo mnsMsgInfo) throws Exception {
		logger.info("贷款消息："+ JSON.toJSONString(mnsMsgInfo));
		Map<String, String> msgInfo = StringUtil.getObject(mnsMsgInfo.getBody(), Map.class);
		OrderModel orderModel = this.orderDao.getModelById(msgInfo.get("order_id"), false);
		Assert.notNull(orderModel, "订单信息为空");

        FundChannelEnum availableFundChannel = FundChannelEnum.parse(orderModel.getFund_channel());
        Assert.notNull(availableFundChannel, "资金渠道配不存在");

        FundLoanApplyModel fundLoanApplyModel = this.fundLoanApplyDao.getModelOne(FrameUtil.newHashMap("order_id",orderModel.getOrder_id(),"fund_channel",availableFundChannel.getCode(),"bus_type",1),true);
        if(fundLoanApplyModel!=null){
            logger.info("贷款申请已发送资金方，等待审核："+ JSON.toJSONString(mnsMsgInfo));
            return;
        }

        UserDataModel userData = this.userDataDao.getModelById(orderModel.getUser_id(), false);
		Assert.notNull(userData, "借款人信息为空");

		BankModel bank = this.bankDao.getModelById(orderModel.getUser_id(), false);
		Assert.notNull(bank, "借款人银行信息为空");

		OrganizationModel organizationModel = organizationService.getModelById(orderModel.getOrg_id(), DbWREnums.READ);
		Assert.notNull(organizationModel, "机构信息为空");



        // 发送给第三方的数据
        String requestData = null;
        // 第三方订单号
        String tradeNo = null;

		switch (availableFundChannel) {
			case QIAN_KANG:{
                QKLoanApplyModel applyModel = QianKangServer.buildLoanApplyModel(organizationModel, orderModel, userData, bank);
                QKLoanApplyResponse applyResponse = QianKangServer.loanApply(orderModel.getOrder_id(), applyModel);
				Assert.notNull(applyResponse, "申请失败，请稍后重试。");
                requestData = JSON.toJSONString(applyModel);
                tradeNo = applyResponse.getOrder_id();
                break;
            }
            default:{}
        }

        Assert.hasLength(requestData, "请求数据为空");
        Assert.hasLength(tradeNo, "非法的第三方订单号");
		// 记录申请记录及第三方订单号
		FundLoanApplyModel apply = new FundLoanApplyModel();
		apply.setFund_channel(availableFundChannel.getValue());
		apply.setBus_type(BusTypeEnum.LOAN_APPLY.getCode());
		apply.setOrder_id(orderModel.getOrder_id());
		apply.setUser_id(orderModel.getUser_id());
		apply.setPrice(orderModel.getOrder_amount());
		apply.setLoan_price(orderModel.getLoan_amount());
		apply.setPeriods(orderModel.getPeriod());
		apply.setLoan_rate(orderModel.getLoan_rate());
		apply.setRepayment_type(1);//1等额本息 2 每月还息，到期还本
		apply.setPayee_name(organizationModel.getPayee_bank_account());
		apply.setPayee_bank_no(organizationModel.getPayee_bank_card());
		apply.setOrg_id(organizationModel.getOrg_id());
		apply.setAsk_data(requestData);
		apply.setStatus(LoanApplyStatusEnum.APPLYING.getCode());
		apply.setTrade_no(tradeNo);
		Long currentTime = FrameUtil.getTime();
		apply.setCreate_time(currentTime);
		apply.setUpdate_time(currentTime);
		this.fundLoanApplyDao.insertModel(apply, true);
	}

	@Override
	public void loanApplyPassProcess(Long order_id) throws Exception {
		Assert.notNull(order_id, "参数不能为空！");

		OrderModel orderModel = orderDao.getModelById(order_id, true);
		Assert.notNull(orderModel, "订单不存在");

		if (StagesStatusEnum.LOAN_APPLY.getCode() != orderModel.getStatus()) {
			FrameUtil.throwBaseException1("当前订单状态不可修改");
		}

		// 拉取还款报表
		this.createOrUpdateRepaymentPlan(orderModel, 0);

		long currtime = FrameUtil.getTime();
		//获取当前时间的00:00:00 计息时间为商户确认的结算日
		Long currDate = DateUtil.getTimeDayByTimestamp(currtime);
		//更新订单状态
		if ( orderDao.updateByMap( FrameUtil.newHashMap("order_id", order_id, "where_status", StagesStatusEnum.LOAN_APPLY.getCode(), "status",
				StagesStatusEnum.REPAYMENTING.getCode(), "last_update_time", currtime, "confirm_time", currtime, "clear_date", currDate), true)!= 1) {
			FrameUtil.throwBaseException1("资金审核通过，更新订单表失败");
	    }

		//记录订单当前状态
		orderStatusService.insert(new OrderStatusModel(orderModel.getOrder_id(), StagesStatusEnum.REPAYMENTING, StagesEventEnum.FUND_VERIFY.getLabel(), currtime));

		//更新用户资金表信息 累计借款金额+  累计成交金额+  待回收金额+
		if(fundsService.updatByMap(orderModel.getUser_id(),FrameUtil.newHashMap("add_borrow",orderModel.getLoan_amount(),"add_price",
				orderModel.getOrder_amount(),"add_recovery",orderModel.getTotal_amount()))!=1){
			FrameUtil.throwBaseException1("更新用户资金成交信息失败");
		}

		//商户资金表更新 更新普通订单累计金额/待收回收累计金额 vip订单累计金额 vip订单累计首付
		Map updateMFundsParam  = FrameUtil.newHashMap();
		updateMFundsParam.put("update_time",currDate);
		if(OrgMoldEnum.ORDINARY.getCode()==orderModel.getOrder_type()){
			updateMFundsParam.put("add_price",orderModel.getOrder_amount());
		}else if(OrgMoldEnum.VIP.getCode()==orderModel.getOrder_type()){
			updateMFundsParam.put("add_recovery_price",orderModel.getTotal_amount());//待回收金额
			updateMFundsParam.put("add_vip_price",orderModel.getOrder_amount());//订单金额
			updateMFundsParam.put("add_vip_frist_price",orderModel.getPayment());//vip订单累计首付金额
		}
		if(merchantFundsService.updataByMap(orderModel.getOrg_id(),updateMFundsParam)!=1){
			FrameUtil.throwBaseException1("更新商户资金信息失败");
		}

		// 商户确认订单成功消息
		JpushUtil.pushMessage(
				orderModel.getUser_id(),
				Constant.SysParamKeyEnum.PUSH_TPL_LOAN_APPLY_PASS,
				orderModel.getOrder_no());
	}

	@Override
	public List<RepaymentDataModel> createOrUpdateRepaymentPlan(OrderModel order, int period) throws Exception {
		Assert.notNull(order, "订单不存在");

		Map filter = FrameUtil.newHashMap("order_id", order.getOrder_id(), "sort"," estimation_repayment_time asc ");
		if(order.getStatus().intValue() == StagesStatusEnum.REPAYMENED.getCode()){
			return repaymentDataDao.getModelList(filter, false);
		}

		boolean isInsert = false;
		if( repaymentDataDao.getModelListCount(filter, false) < 1 ){
			isInsert = true;
		}

		QKRepaymentPlanModel repaymentPlanModel = QianKangServer.queryRepaymentPlan(order.getOrder_id(), order.getOrder_no(), period);
		List<RepaymentPlanItem> remotePlan = repaymentPlanModel.getRepayment_list();
		if(remotePlan.size() != order.getPeriod()){
			FrameUtil.throwBaseException1("还款报表期数不正确");
		}

		long currtime = FrameUtil.getTime();

        // 格式yyyyMM
        int currentMonth = DateUtil.parseTimestamp(currtime, DateUtil.PATTERN_yyyyMM);
        int repaymentPlanMonth = currentMonth;

        // 需要更新的订单信息
		int limit_pay = order.getLimit_pay(); // 已还期数
        Double interest_price = 0.0; // 利息金额
		Double interest_pay = 0.0; // 已还金额
		Double fine_price = 0.0; // 罚息金额
		Double total_amount = 0.0; // 应还总金额(贷款金额+利息)

        RepaymentPlanItem itm = null;
        List<RepaymentDataModel> latestRepaymentList = new ArrayList<RepaymentDataModel>();

		// 还款报表按还款日期升序，所以idx即对应的期数
		for (int idx = 1; idx < remotePlan.size()+1; idx++) {
			itm = remotePlan.get(idx -1);
            repaymentPlanMonth = DateUtil.parseTimestamp(
                    DateUtil.dateStringToTimestamp(itm.getRepayment_date(), DateUtil.PATTERN_yyyy_MM_dd), DateUtil.PATTERN_yyyyMM);

			// 已经还款的报表不再更新
			if(idx <= order.getLimit_pay()){
				continue;
			}
			// 更新时，下个月之后的还款报表不更新（兼容提前把下个月还了的情况）
			if(!isInsert && repaymentPlanMonth > currentMonth + 1){
			    break;
            }

            // 累计 应还总金额
			total_amount = ArithUtil.add(total_amount,
					ArithUtil.formatToYuan(ArithUtil.add(itm.getRepayment_corpus(), itm.getRepayment_interest())));

			if( itm.getStatus() == 4 ){
				limit_pay = idx;
                interest_price = ArithUtil.add(interest_price, ArithUtil.formatToYuan(itm.getRepayment_interest()));
				interest_pay = ArithUtil.add(interest_pay, ArithUtil.formatToYuan(itm.getRepayment_amount()));
				fine_price = ArithUtil.add(fine_price, ArithUtil.formatToYuan(itm.getOverdue_penalty()));
			}

			RepaymentDataModel dataModel = new RepaymentDataModel();
			dataModel.setOrder_id(order.getOrder_id());//主订单id
			dataModel.setPeriod(idx);//还款期数
			dataModel.setEstimation_repayment_time(DateUtil.dateStringToTimestamp(itm.getRepayment_date(), DateUtil.PATTERN_yyyy_MM_dd));//还款日期
			dataModel.setOverdue_price(ArithUtil.formatToYuan(itm.getOverdue_penalty()));//罚息默认为0
			dataModel.setOverdue_day(itm.getOverdue_days());
			dataModel.setCapital(ArithUtil.formatToYuan(itm.getRepayment_corpus()));//应还本金
			dataModel.setInterest(ArithUtil.formatToYuan(itm.getRepayment_interest()));//等额本息默认为0
			dataModel.setDiscount_amount(0d);//减免金额
			dataModel.setRepayment(ArithUtil.formatToYuan(itm.getActual_amount()));//实还金额
			dataModel.setRepayment_time(0L);
			if(StringUtil.isNotEmpty(itm.getActual_time())){
				dataModel.setRepayment_time(DateUtil.dateStringToTimestamp(itm.getActual_time(), DateUtil.PATTERN_yyyyMMddHHmmss));
			}
			dataModel.setRepayment_amount(ArithUtil.formatToYuan(itm.getRepayment_amount()));//还款金额
			dataModel.setRepayment_status( itm.getStatus() == 4 ? 1 : 0);//还款状态
			if(isInsert){
				dataModel.setCreate_time(currtime);//生成时间
			}
			dataModel.setLast_update_time(currtime);//修改时间
			dataModel.setUser_id(order.getUser_id());//用户id
			dataModel.setOrg_id(order.getOrg_id());//机构id
			dataModel.setVersion(0L);
			dataModel.setRepayment_type(RepaymentTypeEnum.TYPE_3.getCode());
			latestRepaymentList.add(dataModel);
		}

		// limit_pay大于订单已还期数，说明有新增还款，需要更新
        if(limit_pay > order.getLimit_pay()){
            Map<Object, Object> updateData = FrameUtil.newHashMap();
            updateData.put("order_id", order.getOrder_id());
            updateData.put("interest_pay", interest_pay);
            updateData.put("fine_price", fine_price);
            updateData.put("limit_pay", limit_pay);
            if(limit_pay == order.getPeriod().intValue()){
                // 如果是最后一期还了，则更新订单为还款完成状态
                updateData.put("status", StagesStatusEnum.REPAYMENED.getCode());


            }
            updateData.put("last_update_time", currtime);
            orderDao.updateByMap(updateData, true);
        }

		// 本地不存在，则创建新的还款计划
		if( isInsert ){
			repaymentDataDao.insertBatch(latestRepaymentList, true);
			orderDao.updateByMap(FrameUtil.newHashMap("order_id", order.getOrder_id(), "total_amount", total_amount), true);
		}
		// 更新
		else {
			if(latestRepaymentList.size() > 0){
				repaymentDataDao.updateBatch(latestRepaymentList, true);
			} else {
                latestRepaymentList = repaymentDataDao.getModelList(filter, false);
            }
		}

		return latestRepaymentList;
	}

	@Override
	public void loanApplyFailProcess(Long order_id,String msg) throws Exception {
		if(order_id==null||StringUtil.isEmpty(msg)){
			FrameUtil.throwBaseException1("请求参数不能为空！");
		}
		OrderModel orderModel = orderDao.getModelById(order_id, true);
		Assert.notNull(orderModel, "订单不存在");

		if (StagesStatusEnum.LOAN_APPLY.getCode() != orderModel.getStatus()) {
			FrameUtil.throwBaseException1("当前订单状态不可修改");
		}
		long currtime = FrameUtil.getTime();
		//获取当前时间的00:00:00 计息时间为商户确认的结算日
		Long currDate = DateUtil.getTimeDayByTimestamp(currtime);
		//更新订单状态
		if (orderDao.updateByMap(FrameUtil.newHashMap("order_id", order_id, "where_version", orderModel.getVersion(), "status",
				StagesStatusEnum.FUND_REFUSE.getCode(), "last_update_time", currtime, "confirm_time", currtime, "clear_date",
				currDate,"refuse_code", OrderRefuseEnum.C.getCode()), true) != 1) {
			FrameUtil.throwBaseException1("资金方审核失败，更新订单表失败");
		}
		//记录拒绝日志
		OrderRefuseContentModel model = new OrderRefuseContentModel();
		model.setContent(msg);
		model.setOrder_id(order_id);
		model.setCreate_time(currtime);
		orderRefuseContentService.insert(model);
		//记录订单当前状态
		orderStatusService.insert(new OrderStatusModel(orderModel.getOrder_id(), StagesStatusEnum.FUND_REFUSE, StagesEventEnum.FUND_VERIFY.getLabel(), currtime));

		// 资金方审核拒绝
		JpushUtil.pushMessage(
				orderModel.getUser_id(),
				Constant.SysParamKeyEnum.PUSH_TPL_FUNDCHANNEL_REFUSE,
				orderModel.getOrder_no());
	}

	@Resource
	private IOrderRefuseContentService orderRefuseContentService;

	@Resource
	private IRepaymentDataDao repaymentDataDao;

	@Resource
	private IOrderStatusService orderStatusService;

	@Resource
	private IFundsService fundsService;

	@Resource
	private IMerchantFundsService merchantFundsService;

	@Resource
	private IOrganizationService organizationService;

	@Resource
	private IOrderDao orderDao;

	@Resource
	private IUserDataDao userDataDao;

	@Resource
	private IBankDao bankDao;

	@Resource
	private IFundLoanApplyDao fundLoanApplyDao;

	@Override
	public IBaseDao getBaseDao() {
		return this.fundLoanApplyDao;
	}

}
